import * as Cesium from "cesium";
/**
 * 基于 new Cesium.ScreenSpaceEventHandler 封装的事件管理器
 * new Cesium.ScreenSpaceEventHandler 通过 setInputAction 注册事件时， 同一种类型的事件只能注册一次，无法应对业务应用的交叉事件
 * ScreenHandeler 二次封装了 事件注册以及销毁，实现了以下几点
 * 1. 实现对同一种Cesium 事件的多次注册
 * 2. 实现对每一次的事件的自定义注销
 * 3. 实现基于事件注册销毁的响应式触发，避免闭包泄露
 *
 * 注意事项：
 * 1. 注册基于 Cesium.ScreenSpaceEventType 的事件类型
 * 2. 自定义类型：customType 与  cesium事件类型：CesiumEvnetType 能够确定该事件， 注册时没有做唯一值的处理，销毁时，会销毁这两种类型的所有事件
 */
export default class CesiumScreenHandeler {
  constructor(viewer) {
    this._handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); // 事件对象，每种类型的事件只能注册一次
    this._eventObj = {}; // 事件管理对象
    // 根据事件类型，设置事件回调对象, 基于 Cesium.ScreenSpaceEventType 二次开发
    for (let key in Cesium.ScreenSpaceEventType) {
      const value = Cesium.ScreenSpaceEventType[key];
      this._eventObj[value] = {
        eventHandler: null, // 权柄
        eventList: [], // 事件对象
        eventKey: key, // 事件标识符
        evnetValue: value,
      };
    }
    console.log("事件管理器：实例化成功 this._eventObj", this._eventObj);
  }
  /**
   * 注册事件
   * @param {* 事件} callback
   * @param {* 自定义类型} customType
   * @param {* Cesium.ScreenSpaceEventType 的类型} CesiumEvnetType
   */
  addHandelEvent(callback, customType, CesiumEvnetType) {
    const eventItem = this._eventObj[CesiumEvnetType];
    if (eventItem) {
      // 新增事件
      eventItem.eventList.push({
        callback,
        customType,
      });
      // 动态判断 是要需要注册handel 事件
      if (!eventItem.eventHandler) {
        eventItem.eventHandler = true;
        this._handler.setInputAction((event) => {
          eventItem.eventList.forEach((item) => {
            item.callback(event);
          });
        }, eventItem.evnetValue);
        console.log("事件管理器：新增事件 eventItem ", eventItem);
      }
    } else {
      console.error(
        "事件管理器：新增事件 出现异常 请检查CesiumEvnetType的类型,应该是 Cesium.ScreenSpaceEventType的类型"
      );
    }
  }
  /**
   * 销毁事件
   * @param {* 自定义类型} customType 
   * @param {* Cesium.ScreenSpaceEventType 的类型} CesiumEvnetType 
   */
  removeHandelEvnet(customType, CesiumEvnetType) {
    const eventItem = this._eventObj[CesiumEvnetType];
    if (eventItem) {
      // 删除 customType, CesiumEvnetType 指定的事件
      eventItem.eventList = eventItem.eventList.filter(
        (item) => item.customType !== customType
      );
      // 如果事件队列为空，则注销 handel 事件
      if (eventItem.eventList.length === 0 && eventItem.eventHandler) {
        eventItem.eventHandler = false;
        this._handler.removeInputAction(eventItem.evnetValue); // 移除事件
        console.log("事件管理器：移除事件 eventItem", eventItem);
      }
    } else {
      console.error(
        "事件管理器：新增事件 出现异常 请检查CesiumEvnetType的类型,应该是 Cesium.ScreenSpaceEventType的类型"
      );
    }
  }
  /**
   * 销毁所有事件
   */
  removeAllHandelEvent() {
    // 销毁所有事件
    for (let key in this._eventObj) {
      const eventItem = this._eventObj[key];
      if (eventItem.eventHandler) {
        eventItem.eventList = []; // 清空队列
        this._handler.removeInputAction(eventItem.evnetValue); // 移除事件
      }
    }
  }
}
